/*  mudmap - A tool to create and organize user side maps for MUD games
 *  Copyright (C) 2012  Neop (aka moemneop, email: mneop@web.de)
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful, but
 *  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 *  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
 *  for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#include "worldmgr.h"

worldmgr *worldmgr::instance = nullptr;

worldmgr::worldmgr(){
    content = vbox_worlds = nullptr;
    read_available();
}

worldmgr::~worldmgr(){
    write_available();
}

worldmgr *worldmgr::get_instance(){
    if(instance == nullptr) instance = new worldmgr();
    return instance;
}

void worldmgr::load_world(string file, bool force){
    if(worlds[file] != nullptr && !force) return;
    worlds[file] = shared_ptr<world>(new world(file));
    add_available(worlds[file]->name, file);
}

shared_ptr<world> worldmgr::get_world(string file){
    if(worlds[file] == nullptr) load_world(file);
    return worlds[file];
}

void worldmgr::create_world(string name, string file){
    shared_ptr<world> nw = shared_ptr<world>(new world(""));
    nw->name = name;
    nw->file = file;
    nw->save();
    worlds[file] = nw;
    add_available(name, file);
}

void worldmgr::add_available(string name, string file){
    available_worlds[name] = file;
}

void worldmgr::remove_available(string name){
    available_worlds[name] = "";
    update_dialog();
}

void worldmgr::read_available(){
    vector<string> lines = readfile_sv(path::get_available_worlds_file());
    string name = "";
    string file = "";
    ifstream ifs;
    for(unsigned i = 0; i < lines.size(); i++){
        if((lines[i])[0] == 'n') name = lines[i].substr(2);
        else if((lines[i])[0] == 'f'){
            file = lines[i].substr(2);
            ifs.open(file);
            if(!ifs.is_open()){
                file = file.substr(file.rfind(path::worlds_dir_str));
                ifs.open(file);
                if(!ifs.is_open()) file = "";
            }
            ifs.close();
        }
        if(name != "" && file != ""){
            available_worlds[name] = file;
            name = file = "";
        }
    }
    update_dialog();
}

void worldmgr::write_available(){
    ofstream ofs(path::get_available_worlds_file(), ios::trunc);
    if(ofs.is_open()){
        for(map<string, string>::iterator it = available_worlds.begin(); it != available_worlds.end(); it++) if(it->first != "" && it->second != "") ofs << "n " << it->first << endl << "f " << it->second << endl;
    } else {
        GtkWidget *dlg = gtk_message_dialog_new(nullptr, GtkDialogFlags(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), GTK_MESSAGE_WARNING, GTK_BUTTONS_OK, _("Couldn't open available worlds file (%s)"), path::get_available_worlds_file().c_str());
        gtk_widget_show_all(dlg);
        gtk_dialog_run(GTK_DIALOG(dlg));
        gtk_widget_destroy(dlg);
    }
    update_dialog();
}

vector<pair<string, string> > worldmgr::get_available(){
    list<string> names_list;
    vector<pair<string, string> > ret;
    for(map<string, string>::iterator it = available_worlds.begin(); it != available_worlds.end(); it++) if(it->first != "" && it->second != "") names_list.push_back(it->first);
    names_list.sort();
    for(list<string>::iterator it = names_list.begin(); it != names_list.end(); it++) ret.push_back(pair<string, string>(*it, available_worlds[*it]));
    return ret;
}

vector<pair<string, string> > available_worlds_vec;

void worldmgr::update_dialog(button_func overview_open_world_func){
    if(overview_open_world_func != nullptr){
        this->overview_open_world_func = overview_open_world_func;
    }
    if(this->overview_open_world_func != nullptr){
        if(content == nullptr){
            content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
            gtk_widget_set_size_request(content, 750, 500);

            GtkWidget *label_available_worlds = gtk_label_new(_("Available worlds:"));
            gtk_box_pack_start(GTK_BOX(content), label_available_worlds, false, false, 5);

            scroll_available_worlds = gtk_scrolled_window_new(nullptr, nullptr);
            gtk_box_pack_start(GTK_BOX(content), scroll_available_worlds, true, true, 5);
        }

        available_worlds_vec = get_instance()->get_available();

        if(vbox_worlds != nullptr) gtk_widget_destroy(vbox_worlds);
        vbox_worlds = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
        gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scroll_available_worlds), vbox_worlds);

        for(unsigned i = 0; i < available_worlds_vec.size(); i++){
            GtkWidget *hbox_world = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
            gtk_box_pack_start(GTK_BOX(vbox_worlds), hbox_world, false, false, 0);

            GtkWidget *button_open = gtk_button_new_with_label(available_worlds_vec[i].first.c_str());
            gtk_box_pack_start(GTK_BOX(hbox_world), button_open, true, true, 0);
            g_signal_connect(button_open, "clicked", G_CALLBACK(this->overview_open_world_func), &available_worlds_vec[i].second);

            GtkWidget *button_remove = gtk_button_new();
            gtk_button_set_image(GTK_BUTTON(button_remove), gtk_image_new_from_stock(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
            gtk_box_pack_start(GTK_BOX(hbox_world), button_remove, false, false, 0);
            g_signal_connect(button_remove, "clicked", G_CALLBACK(overview_delete_world_func), &available_worlds_vec[i].first);
        }
        gtk_widget_show_all(content);
    }
}

GtkWidget *worldmgr::get_content(){
    return content;
}

GtkWidget *worldmgr::get_label(){
    return gtk_label_new(_("Overview"));
}

void worldmgr::overview_delete_world_func(GtkToolButton *toolbutton, gpointer user_data){
    string name = *(string*)((void*) user_data);
    GtkWidget *dialog = gtk_message_dialog_new(nullptr, GtkDialogFlags(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO, _("The world %s will be deleted!"), name.c_str());
    gtk_widget_show(dialog);
    if(gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES){
        #ifndef __linux__
            string com = "del " + get_instance()->available_worlds[name];
            string com_meta = com + "_meta";
        #else
            string com = "rm " + get_instance()->available_worlds[name];
            string com_meta = com + "_meta";
        #endif
        //cout << name << endl << com << endl << com_meta << endl;
        int a = system(com.c_str());
        a = system(com_meta.c_str());
        a = a + a; // TODO: -Wunused-result is annoying :C
        get_instance()->remove_available(name);
    }
    gtk_widget_destroy(dialog);
}
